The Java language has rapidly been gaining importance as a standard object-oriented programming language since its advent in late 1995. “Java” is a trademark of Sun Microsystems, Inc. Java programs (also known as Java class files) are converted from a well defined application program source code into an architecture-neutral, machine independent code, called Java bytecode. The Java bytecodes are designed to execute on a Java Virtual Machine (JVM). A JVM is not an actual hardware platform, but is a low level software emulator that can be implemented on many different computer processor architectures and under many different computer operating systems. Thus, the JVM is a virtual computer component that resides only in the memory of a computer platform.
Once an application program source code has been converted into a Java program comprising Java bytecode sequences, the bytecode sequences are then interpreted by a JVM interpreter for each platform. A Java interpreter is a module of the JVM that alternatively decodes and executes the bytecode sequences. Although its platform-neutrality, flexibility, and reusability are all advantages for a programming language, the execution by interpretation imposes an unacceptable performance penalty, mainly on account of the run-time overhead of the bytecode instruction fetch and decode.
One means of improving the run-time performance of an executed program is to use a Java just-in-time (JIT) compiler, which compiles the Java class files “on the fly” into equivalent sequences of the native code of the underlying machine. Such JIT compiled native machine code executes more quickly than Java class files that are decoded and executed using a Java interpreter thus significantly improving the performance of program execution, but the overall program execution time, in contrast to that of a conventional static compiler, now includes the compilation overhead of the JIT compiler. It is therefore important for the JIT compiler to be fast and lightweight, as well as to generate high-quality native code. This is particularly true for applications where Java programs are distributed in real time across a computer network such as the Internet.
The use of variant flags is known in the Java programming language. A variant flag is an application flag whose value can change at runtime. It is known to use variant flags in connection with conditional checking statements to determine, at run-time, whether a program routine has been activated or deactivated. It can be desirable to defer decisions regarding the inclusion or exclusion of software routines in the execution of an application program until run-time. These routines are referred to as “run-time determined software routines”. An example of a run-time determined software routine in a Java program is the method of logging/tracing the execution of methods of a Java class file. A determination to execute such a run-time determined software routine can be made by including a conditional checking statement which checks a variant flag in the form of a Boolean parameter at every method entry and exit to determine if the routine has been activated at run-time. If the routine has been activated, it can be executed. However, if the routine is determined not to have been activated, it can be skipped. The Boolean parameter is variable in that it can be changed during run-time by a program user to activate or deactivate the routine as required. A drawback with this technique of determining whether a run-time determined software routine has been activated and is thus to be executed or has been deactivated and is thus to be skipped is that all run-time determined software routines need to be included in the application program in the event that any of them are activated during run-time. As a consequence, the application program has a large footprint at run-time which is undesirable for Java JIT compilation environments. In addition, the conditional checking statements take time to evaluate which increases the run-time overhead of the application program.
Java JIT compilers can perform optimisations on the compiled Java program including method inlining, exception check elimination, common sub-expression elimination and loop versioning. In addition, one optimisation a JIT compiler can undertake is to exclude redundant data from the compiled native machine code. Redundant code includes code which is never executed and code which always resolves to a known, discrete result. However, a variant flag prevents a Java JIT compiler from excluding conditional checking statements and thus run-time determined software routines from compiled native machine code even when the run-time determined software routine has been deactivated because the conditional checking statements are indeterminate due to the use of the variant flag.